﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Documents;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Controls;
using Pavilion.DesignerTool.ViewTools;

namespace Pavilion.DesignerTool
{
    static public class CircleAdornerDisplay
    {
        #region IsCircleVisibleProperty

        public static readonly DependencyProperty IsCircleVisibleProperty = DependencyProperty.RegisterAttached("IsCircleVisible", typeof(Boolean), typeof(CircleAdornerDisplay),
            new FrameworkPropertyMetadata(IsCircleVisible_PropertyChanged));

        public static void SetIsCircleVisible(DependencyObject element, Boolean value)
        {
            element.SetValue(IsCircleVisibleProperty, value);
        }

        public static Boolean GetIsCircleVisible(DependencyObject element)
        {
            return (Boolean)element.GetValue(IsCircleVisibleProperty);
        }

        #endregion

        private static Dictionary<FrameworkElement, CircleAdorner> circledElementsDictionary = new Dictionary<FrameworkElement, CircleAdorner>();

        public static void AttachCircleAroundElement(FrameworkElement element)
        {
            if (circledElementsDictionary.ContainsKey(element))
                return;

            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(element);
            CircleAdorner circleAdorner = new CircleAdorner(element);
            adornerLayer.Add(circleAdorner);

            circledElementsDictionary.Add(element, circleAdorner);
        }

        public static void DetachCircleAroundElement(FrameworkElement element)
        {
            if (!circledElementsDictionary.ContainsKey(element))
                return;

            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(element);
            adornerLayer.Remove(circledElementsDictionary[element]);
            circledElementsDictionary.Remove(element);
        }

        public static void IsCircleVisible_PropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            if ((bool)args.NewValue)
                AttachCircleAroundElement(obj as FrameworkElement);
            else
                DetachCircleAroundElement(obj as FrameworkElement);
        }
    }

    public class CircleAdorner : Adorner
    {
        private Ellipse child;

        public CircleAdorner(FrameworkElement adornedElement) : base(adornedElement)
        {
            adornedElement.SizeChanged += new SizeChangedEventHandler(AdornedElement_SizeChanged);

            this.child = new Ellipse();
            this.child.VerticalAlignment = VerticalAlignment.Center;
            this.child.HorizontalAlignment = HorizontalAlignment.Center;
            this.child.Stroke = Brushes.DarkOrange;
            this.child.StrokeThickness = 2;
            this.child.IsHitTestVisible = false;

            UpdateEllipseSize(adornedElement.ActualWidth, adornedElement.ActualHeight);
        }

        private void AdornedElement_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            UpdateEllipseSize(e.NewSize.Width, e.NewSize.Height);
        }

        private void UpdateEllipseSize(double width, double height)
        {
            this.child.Width = width + 50;
            this.child.Height = height + 50;

            double xOffset = (-this.child.Width / 2) + (width / 2);
            double yOffset = (-this.child.Height / 2) + (height / 2);

            this.child.Margin = new Thickness(xOffset, yOffset, 0, 0);
        }

        protected override int VisualChildrenCount { get { return 1; } }

        protected override System.Windows.Size MeasureOverride(System.Windows.Size constraint)
        {
            this.child.Measure(constraint);
            return this.child.DesiredSize;
        }

        protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
        {
            this.child.Arrange(new Rect(finalSize));
            return finalSize;
        }

        protected override System.Windows.Media.Visual GetVisualChild(int index)
        {
            return this.child;
        }
    }
}
